package com.party.web.biz.openPlatform;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.party.api.dto.wechat.requst.MenuButtonRequest;
import com.party.api.dto.wechat.response.GetMenuResponse;
import com.party.api.dto.wechatPlatform.response.WechatAuthorizerInfoResponse;
import com.party.api.dto.wechatPlatform.response.WechatAuthorizerUserInfoResponse;
import com.party.api.service.wechat.IWechatService;
import com.party.common.constant.Constant;
import com.party.common.utils.StringUtils;
import com.party.common.utils.refund.WechatPayUtils;
import com.party.core.model.member.DeployType;
import com.party.core.model.member.MemberExternalApp;
import com.party.core.model.wechat.WechatMenu;
import com.party.core.model.wechat.WechatMenuActionType;
import com.party.core.model.wechatPlatform.WechatOpenMember;
import com.party.core.service.member.IMemberExternalAppService;
import com.party.core.service.wechat.IWechatMenuService;
import com.party.core.service.wechatPlatform.IWechatOpenMemberService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

/**
 * 开放平台的第三方平台授权业务
 */
@Service
public class AuthorizationBizService {

    protected static Logger logger = LoggerFactory.getLogger(AuthorizationBizService.class);
    @Autowired
    private IWechatOpenMemberService wechatOpenMemberService;

    @Autowired
    private IWechatService wechatService;

    @Autowired
    private IWechatMenuService wechatMenuService;

    @Autowired
    private IMemberExternalAppService memberExternalAppService;

    /**
     * 2、获取第三方平台component_access_token
     *
     * @param appid        第三方平台appid
     * @param appsecret    第三方平台appsecret
     * @param verifyTicket 微信后台推送的ticket，此ticket会定时推送
     * @return 第三方平台access_token
     */
    public String getAccessToken(String appid, String appsecret, String verifyTicket) {
        String requestUrlFormat = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
        Map<String, Object> requestMap = Maps.newHashMap();
        requestMap.put("component_appid", appid); // 第三方平台appid
        requestMap.put("component_appsecret", appsecret); //第三方平台appsecret
        requestMap.put("component_verify_ticket", verifyTicket); // 微信后台推送的ticket
        String requestJson = JSONObject.toJSONString(requestMap);
        logger.info("获取第三方平台component_access_token 请求参数{}", requestJson);
        String responseData = WechatPayUtils.httpsPost(requestUrlFormat, requestJson);
        logger.info("获取第三方平台component_access_token 响应参数{}", responseData);
        if (StringUtils.isNotEmpty(responseData)) {
            Map responseMap = JSONObject.parseObject(responseData, Map.class);
            String accessToken = (String) responseMap.get("component_access_token"); // 第三方平台access_token
            return accessToken;
        }
        return null;
    }

    /**
     * 3、获取预授权码pre_auth_code
     *
     * @param appid       第三方平台方appid
     * @param accessToken 第三方平台access_token
     * @return
     */
    public String getPreAuthCode(String appid, String accessToken) {
        String requestUrlFormat = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token={0}";
        Map<String, Object> requestMap = Maps.newHashMap();
        requestMap.put("component_appid", appid);
        String requestJson = JSONObject.toJSONString(requestMap);
        logger.info("获取获取预授权码pre_auth_code 请求参数{}", requestJson);
        String requestUrl = requestUrlFormat.replace("{0}", accessToken);
        String responseData = WechatPayUtils.httpsPost(requestUrl, requestJson);
        logger.info("获取获取预授权码pre_auth_code 响应参数{}", responseData);
        if (StringUtils.isNotEmpty(responseData)) {
            Map responseMap = JSONObject.parseObject(responseData, Map.class);
            String preAuthCode = (String) responseMap.get("pre_auth_code");
            return preAuthCode;
        }
        return null;
    }

    /**
     * 获取授权URL
     *
     * @param redirectUrl    重定向地址
     * @param componentAppid 第三方平台appid
     * @param authCode       预授权码
     * @return
     */
    public String getAuthorizeUrl(String redirectUrl, String componentAppid, String authCode) throws UnsupportedEncodingException {
        String requestUrlFormat = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=APPID&pre_auth_code=AUTH_CODE&redirect_uri=REDIRECT_URI";
        redirectUrl = URLEncoder.encode(redirectUrl, Constant.UTF_8);
        authCode = URLEncoder.encode(authCode, Constant.UTF_8);
        String authorizationUrl = requestUrlFormat.replace("APPID", componentAppid)
                .replace("AUTH_CODE", authCode)
                .replace("REDIRECT_URI", redirectUrl);
        return authorizationUrl;
    }

    /**
     * 获取授权信息
     *
     * @param componentAppid       第三方平台appid
     * @param componentAccessToken 第三方平台access_token
     * @param authorizationCode    授权code,会在授权成功时返回给第三方平台
     * @return
     */
    public WechatAuthorizerInfoResponse getAuthorizationInfo(String componentAppid, String componentAccessToken, String authorizationCode) {
        String requestUrlFormat = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token={0}";
        Map<String, Object> requestMap = Maps.newHashMap();
        requestMap.put("component_appid", componentAppid);
        requestMap.put("authorization_code", authorizationCode);
        String requestJson = JSONObject.toJSONString(requestMap);
        logger.info("授权 请求参数{}", requestJson);
        String requestUrl = requestUrlFormat.replace("{0}", componentAccessToken);
        String responseData = WechatPayUtils.httpsPost(requestUrl, requestJson);
        logger.info("授权 响应参数{}", responseData);
        if (StringUtils.isNotEmpty(responseData)) {
            WechatAuthorizerInfoResponse authorizationInfo = JSONObject.parseObject(responseData, WechatAuthorizerInfoResponse.class);
            return authorizationInfo;
        }
        return null;
    }

    /**
     * 获取授权方的帐号基本信息
     *
     * @param componentAppid       服务appid
     * @param authorizerAppid      授权方appid
     * @param componentAccessToken 第三方平台access_token
     */
    public WechatAuthorizerUserInfoResponse getAuthorizerInfo(String componentAppid, String authorizerAppid, String componentAccessToken) {
        String requestUrlFormat = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token={0}";
        Map<String, Object> params = Maps.newHashMap();
        params.put("component_appid", componentAppid);
        params.put("authorizer_appid", authorizerAppid);
        String requestData = JSONObject.toJSONString(params);
        String requestUrl = requestUrlFormat.replace("{0}", componentAccessToken);
        logger.info("获取授权方的帐号基本信息 请求参数{}", requestData);
        String responseData = WechatPayUtils.httpsPost(requestUrl, requestData);
        logger.info("获取授权方的帐号基本信息 响应参数{}", responseData);
        if (StringUtils.isNotEmpty(responseData)) {
            WechatAuthorizerUserInfoResponse authorizerUserInfo = JSONObject.parseObject(responseData, WechatAuthorizerUserInfoResponse.class);
            return authorizerUserInfo;
        }
        return null;
    }

    /**
     * 保存接口调用凭据和授权信息
     *
     * @param authorizationInfo
     * @param memberId
     * @return
     */
    public WechatOpenMember saveAuthorizerInfo(WechatAuthorizerInfoResponse authorizationInfo, String memberId) {

        //根据appId查询，没有则新增。mvn
        WechatAuthorizerInfoResponse.AuthorizationInfo authorization_info = authorizationInfo.getAuthorization_info();
        WechatOpenMember wechatOpenMember
                = wechatOpenMemberService.findByAppidAndDeployType(authorization_info.getAuthorizer_appid(),
                DeployType.AUTHORIZATION.getCode());
        if (null == wechatOpenMember){
            wechatOpenMember = new WechatOpenMember();
            wechatOpenMember.setAuthorizerAppid(authorization_info.getAuthorizer_appid());
            wechatOpenMember.setAuthorizerAccessToken(authorization_info.getAuthorizer_access_token());
            wechatOpenMember.setAuthorizerRefreshToken(authorization_info.getAuthorizer_refresh_token());
            wechatOpenMember.setType("PARTNER");
            wechatOpenMemberService.insert(wechatOpenMember);
        }
        else {
            wechatOpenMember.setAuthorizerAppid(authorization_info.getAuthorizer_appid());
            wechatOpenMember.setAuthorizerAccessToken(authorization_info.getAuthorizer_access_token());
            wechatOpenMember.setAuthorizerRefreshToken(authorization_info.getAuthorizer_refresh_token());
            wechatOpenMemberService.update(wechatOpenMember);
        }

        //保存分配关系
        MemberExternalApp memberExternalApp
                = memberExternalAppService.getSet(memberId, DeployType.AUTHORIZATION.getCode());
        memberExternalApp.setExternalAccountId(wechatOpenMember.getId());
        memberExternalAppService.update(memberExternalApp);
        try {
            synchronousMenu(wechatOpenMember.getAuthorizerAccessToken(), memberId);
        } catch (Exception e) {
            logger.error("同步菜单信息异常", e);
        }
        return wechatOpenMember;
    }

    /**
     * 保存授权方的帐号基本信息
     *
     * @param authorizerInfo 授权者信息
     * @param openMember 开放平台信息
     * @return 开放平台信息
     */
    public WechatOpenMember saveAuthorizerBaseInfo(WechatAuthorizerUserInfoResponse authorizerInfo,
                                                   WechatOpenMember openMember) {

        // 授权信息
        WechatAuthorizerUserInfoResponse.AuthorizationInfo authorization_info = authorizerInfo.getAuthorization_info();

        // 授权者信息
        WechatAuthorizerUserInfoResponse.AuthorizerUserInfo authorizer_info = authorizerInfo.getAuthorizer_info();

        //授权方昵称
        openMember.setNickName(authorizer_info.getNick_name());

        //授权方头像
        openMember.setHeadImg(authorizer_info.getHead_img());

        //授权方公众号类型
        openMember.setServiceTypeInfo(authorizer_info.getService_type_info().getId());

        //授权方认证类型
        openMember.setVerifyTypeInfo(authorizer_info.getVerify_type_info().getId());

        //授权方公众号的原始ID
        openMember.setUserName(authorizer_info.getUser_name());

        //公众号的主体名称
        openMember.setPrincipalName(authorizer_info.getPrincipal_name());

        //授权方公众号所设置的微信号
        openMember.setAlias(authorizer_info.getAlias());
        openMember.setBusiness_info(JSONObject.toJSONString(authorizer_info.getBusiness_info()));

        //二维码图片的URL
        openMember.setQrcodeUrl(authorizer_info.getQrcode_url());

        // 账号介绍
        openMember.setSignature(authorizer_info.getSignature());

        //授权集合
        openMember.setFuncInfo(JSONObject.toJSONString(authorization_info.getFunc_info()));

        wechatOpenMemberService.update(openMember);
        return openMember;
    }

    /**
     * 同步菜单
     * @param accessToken 公众号交互令牌
     */
    @Transactional
    public void synchronousMenu(String accessToken, String memberId){
        wechatMenuService.deleteByMemberId(memberId);
        GetMenuResponse getMenuResponse = wechatService.getMenu(accessToken);
        if (getMenuResponse.getMenuRequest() != null && getMenuResponse.getMenuRequest().getButton() != null){
            treeToList(getMenuResponse.getMenuRequest().getButton(), Constant.TOP_PARENT_ID, memberId);
        }
    }


    /**
     * 树转list
     * @param list 树结构
     * @param parentId 父级编号
     */
    public void treeToList(List<MenuButtonRequest> list, String parentId, String memberId){
        int index = 0;
        for (MenuButtonRequest menuButtonRequest : list){
            WechatMenu wechatMenu = new WechatMenu();
            wechatMenu.setName(menuButtonRequest.getName());
            wechatMenu.setMemberId(memberId);
            if (WechatMenuActionType.CLICK.getValue().equals(menuButtonRequest.getType())){
                wechatMenu.setActionType(WechatMenuActionType.CLICK.getCode());
            }
            if (WechatMenuActionType.VIEW.getValue().equals(menuButtonRequest.getType())){
                wechatMenu.setActionType(WechatMenuActionType.VIEW.getCode());
                wechatMenu.setUrl(menuButtonRequest.getUrl());
            }
            if("media_id".equals(menuButtonRequest.getType())){
                wechatMenu.setActionType(WechatMenuActionType.NEWS.getCode());
                wechatMenu.setMediaId(menuButtonRequest.getMediaId());
            }
            wechatMenu.setParentId(parentId);
            wechatMenu.setSort(index);
            index++;
            wechatMenuService.insert(wechatMenu);
            if (!CollectionUtils.isEmpty(menuButtonRequest.getButtonRequestList())){
                treeToList(menuButtonRequest.getButtonRequestList(), wechatMenu.getId(), memberId);
            }
        }
    }

}
